﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using AutumnEngine.Modules;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Controllers;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Factories;
using FarseerGames.FarseerPhysics.Interfaces;
using FarseerGames.FarseerPhysics.Collisions;
namespace AutumnEngine.Modules
{
    /// <summary>
    /// Holds all scenes physic simulators and gravitic values, etc.
    /// </summary>
    public class PhysicsManagerModule : Module
    {
        Vector2 wind = Vector2.Zero;
        float strength = 0f;
        float windHeight = 0f;

        public Vector2 Gravity
        {
            get;
            set;
        }

        internal Dictionary<UInt32, PhysicsSimulator> sims;

        internal void AddPhysicsSimulator(UInt32 sceneId)
        {
            if (Engine.Modules.Contains("Engine.Logging"))
                Engine.Modules.Logging.Write("Added simulator for scene " + sceneId.ToString(), LogLevel.Trace);
            PhysicsSimulator s = new PhysicsSimulator(Gravity);
            sims.Add(sceneId, s);
        }

        public override void Create()
        {
            Gravity = new Vector2(0, 9.8f);
            sims = new Dictionary<UInt32, PhysicsSimulator>();
            base.Create();
        }

        public void RemoveSimNodes(UInt32 id)
        {
            sims[id].Clear();
        }

        public override void Update()
        {
            float upd = (float)Engine.GameTime.ElapsedGameTime.Milliseconds * .002f;    
            //Apply wind.
            Vector2 min = Vector2.Subtract(wind, new Vector2(0,windHeight));
            Vector2 max = Vector2.Add(wind, new Vector2(strength * 10, windHeight));

            AABB aabb = new AABB(ref min, ref max);

            foreach (Body body in sims[Engine.Modules.SceneManager.ActiveScene.ID].BodyList)
            {
                if (aabb.Contains(body.Position))
                {
                    body.ApplyForce(new Vector2(400, 0));
                }
            }

            sims[Engine.Modules.SceneManager.ActiveScene.ID].Update(upd);
            base.Update();
        }

        public void AddNode(UInt32 scene, PhysicsSpriteNode b)
        {
            sims[scene].Add(b.Body);
            sims[scene].Add(b.Geom);
        }

        public void ApplyExplosion(Vector2 position, Vector2 size)
        {
            Vector2 min = Vector2.Subtract(position, size / 2);
            Vector2 max = Vector2.Add(position, size / 2);

            AABB aabb = new AABB(ref min, ref max);

            foreach (Body body in sims[Engine.Modules.SceneManager.ActiveScene.ID].BodyList)
            {
                if (aabb.Contains(body.Position))
                {
                    Vector2 fv = body.Position;
                    fv = Vector2.Subtract(fv, position);
                    fv.Normalize();
                    fv = Vector2.Multiply(fv, 50000);
                    body.ApplyForce(fv);
                }
            }
        }

        public void SetWind(Vector2 orig, float windStrength, float height)
        {
            wind = orig;
            strength = windStrength;
            windHeight = height;
        }
    }
}
